package com.ysd.config;

import java.util.LinkedHashMap;
import java.util.Properties;

import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import com.ysd.shiro.CustomRealm;

/**
 * 把Subject、SecurityManager、realm关联起来
 */

@Configuration
public class ShiroConfig {
	
	/**
	 * 使用注解设置权限
	 */
	@Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
	
	/**
     * 解决： 无权限页面不跳转 shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized") 无效
     * shiro的源代码ShiroFilterFactoryBean.Java定义的filter必须满足filter instanceof AuthorizationFilter，
     * 只有perms，roles，ssl，rest，port才是属于AuthorizationFilter，而anon，authcBasic，auchc，user是AuthenticationFilter，
     * 所以unauthorizedUrl设置后页面不跳转 Shiro注解模式下，登录失败与没有权限都是通过抛出异常。
     * 并且默认并没有去处理或者捕获这些异常。在SpringMVC下需要配置捕获相应异常来通知用户信息
     * @return
     */
    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver simpleMappingExceptionResolver=new SimpleMappingExceptionResolver();
        Properties properties=new Properties();
        properties.setProperty("org.apache.shiro.authz.UnauthorizedException","/index/unauthorized");
        properties.setProperty("org.apache.shiro.authz.UnauthenticatedException","/index/unauthorized");
        simpleMappingExceptionResolver.setExceptionMappings(properties);
        return simpleMappingExceptionResolver;
    }
	
	/**
	 * shiro的拦截器
	 * @return
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		//shiro的过滤器对象，拦截请求进行验证
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		
		//没有登录配置跳转到登录页面
		shiroFilterFactoryBean.setLoginUrl("/index/golog");
		
		//登录后没有权限时设置调转的接口
		shiroFilterFactoryBean.setUnauthorizedUrl("/index/unauthorized");
		
		//配置访问权限链 使用LinkedHashMap保证有顺序
		LinkedHashMap<String, String> filterMap = new LinkedHashMap<String, String>();
		
		/*
		 * 第一个参数：访问路径，第二个：权限
		 * anon：没有限制都可以访问
		 * authc：必须登录后才能访问 
		 * user：Remember Me使用
		 * prems：必须有相应的权限才能操作
		 * roles：必须有相应的角色才能操作
		 * 
		 */
		filterMap.put("/index/test", "anon");
		
		filterMap.put("/index/login", "anon");
		filterMap.put("/users/getAll", "anon"); 
		filterMap.put("/roles/findAll", "anon");  
		filterMap.put("/index/require_auth", "authc");
		
		//除了上面配置的特殊请求的权限外其他的所有请求都需要登录权限，这个配置一定要放到最下面
		filterMap.put("/**", "authc");
		
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
		
		return shiroFilterFactoryBean;
	}
	
	/**
	 * 配置Shiro的核心管理器
	 * @return
	 */
	@Bean
	public SecurityManager securityManager() {
		//shiro的核心管理器对象
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		
		//把realm注入到shiro的核心管理器
		securityManager.setRealm(customRealm());
		
		return securityManager;
	}

	/**
	 * 配置自定义realm
	 * @return
	 */
	@Bean
	public CustomRealm customRealm() {
		 
		return new CustomRealm();
	}
	
	
	
}


